fix nmea writer date bug. (#553)
authortsteven4 <13596209+tsteven4@users.noreply.github.com>
Thu, 7 May 2020 12:31:39 +0000 (06:31 -0600)
committerGitHub <noreply@github.com>
Thu, 7 May 2020 12:31:39 +0000 (06:31 -0600)
* fix nmea writer date bug.

dates before 2000 were written with a month off by one.

This also changes the behavior when the creation time is invalid.
Previously you would get data related to the unix epoch for the date
and time fields.
Now you get empty fields, i.e. ",,"

* fix magellan writer date bug.

This had the same bug as nmea.  It had an additional bug
when it attempted to round the fractional part of a second.  Rounding
can ripple all the way from the fractional part of a second to the year,
as is now demonstrated in the testcase.

Like nmea, magellan will now print empty fields if the creation time
is invalid.

* fix date bug in gpssim.

This is the same bug as in nmea, magproto.

gpssim.cc
magproto.cc
nmea.cc
reference/track/magellandate.log [new file with mode: 0644]
reference/track/nmeadate.gpssim [new file with mode: 0644]
reference/track/nmeadate.gpx [new file with mode: 0644]
reference/track/nmeadate.nmea [new file with mode: 0644]
testo.d/gpssim.test
testo.d/magellan.test
testo.d/nmea.test

index 36efa4f1729db6266a39146dc32abecd83ece36a..a7ade098004ed6d451d472b012aaaa812b8bbf11 100644 (file)
--- a/gpssim.cc
+++ b/gpssim.cc
@@ -125,12 +125,10 @@ gpssim_write_pt(const Waypoint* wpt)
   if (wpt->creation_time.isValid()) {
     char tbuf[20];
 
-    const time_t tt = wpt->GetCreationTime().toTime_t();
-    struct tm* tm = gmtime(&tt);
-    int hms = tm->tm_hour * 10000 + tm->tm_min * 100 + tm->tm_sec;
-    int ymd = tm->tm_mday * 10000 + tm->tm_mon * 100 + tm->tm_year;
+    QByteArray dmy = wpt->GetCreationTime().toUTC().toString("ddMMyy").toUtf8();
+    QByteArray hms = wpt->GetCreationTime().toUTC().toString("hhmmss").toUtf8();
 
-    snprintf(tbuf, sizeof(tbuf), ",%d,%d",ymd, hms);
+    snprintf(tbuf, sizeof(tbuf), ",%s,%s",dmy.constData(), hms.constData());
     strcat(obuf, tbuf);
   }
 
index 3b917c6d822bbdbdfb36bab84f85205ba76702af..6a968b5c1bedda983b5b4874ad0ca2de300f87ed 100644 (file)
@@ -20,6 +20,7 @@
 
  */
 
+#include <cassert>                 // for assert
 #include <cctype>                  // for isprint, toupper
 #include <cmath>                   // for fabs, lround
 #include <cstdio>                  // for sscanf, size_t
@@ -28,7 +29,7 @@
 #include <ctime>                   // for gmtime
 
 #include <QtCore/QByteArray>       // for QByteArray
-#include <QtCore/QCharRef>         // for QCharRef
+#include <QtCore/QDateTime>        // for QDateTime
 #include <QtCore/QDir>             // for QDir, operator|, QDir::Files, QDir::Name, QDir::Readable
 #include <QtCore/QFileInfo>        // for QFileInfo
 #include <QtCore/QFileInfoList>    // for QFileInfoList
@@ -38,6 +39,7 @@
 #include <QtCore/QString>          // for QString, operator==
 #include <QtCore/QStringList>      // for QStringList
 #include <QtCore/QTime>            // for QTime
+#include <QtCore/QVector>          // for QVector
 #include <QtCore/Qt>               // for CaseInsensitive
 #include <QtCore/QtGlobal>         // for qPrintable, foreach
 
@@ -1407,27 +1409,20 @@ static
 void mag_track_disp(const Waypoint* waypointp)
 {
   QScopedPointer<char, QScopedPointerPodDeleter> obuf;
-  int hms=0;
-  int fracsec=0;
-  int date=0;
 
   double ilat = waypointp->latitude;
   double ilon = waypointp->longitude;
-  struct tm* tm = nullptr;
+  
+  QByteArray dmy("");
+  QByteArray hms("");
   if (waypointp->creation_time.isValid()) {
-    const time_t ct = waypointp->GetCreationTime().toTime_t();
-    tm = gmtime(&ct);
-    if (tm) {
-      hms = tm->tm_hour * 10000 + tm->tm_min  * 100 +
-            tm->tm_sec;
-      date = tm->tm_mday * 10000 + tm->tm_mon * 100 +
-             tm->tm_year;
-      fracsec = lround(waypointp->GetCreationTime().time().msec()/10.0);
-    }
-  }
-  if (!tm) {
-    date = 0;
-    fracsec = 0;
+    // Round to hundredths of seconds before conversion to string.
+    // Rounding can ripple all the way from the msec to the year.
+    QDateTime dt = waypointp->GetCreationTime().toUTC();
+    dt = dt.addMSecs(10 * lround(dt.time().msec()/10.0) - dt.time().msec());
+    assert((dt.time().msec() % 10) == 0);
+    dmy = dt.toString("ddMMyy").toUtf8();
+    hms = dt.toString("hhmmss.zzz").left(9).toUtf8();
   }
 
   double lon = fabs(ilon);
@@ -1442,12 +1437,12 @@ void mag_track_disp(const Waypoint* waypointp)
   lon = (lon_deg * 100.0 + lon);
   lat = (lat_deg * 100.0 + lat);
 
-  xasprintf(obuf,"PMGNTRK,%4.3f,%c,%09.3f,%c,%05.0f,%c,%06d.%02d,A,,%06d",
+  xasprintf(obuf,"PMGNTRK,%4.3f,%c,%09.3f,%c,%05.0f,%c,%s,A,,%s",
           lat, ilat < 0 ? 'S' : 'N',
           lon, ilon < 0 ? 'W' : 'E',
           waypointp->altitude == unknown_alt ?
           0 : waypointp->altitude,
-          'M', hms, fracsec, date);
+          'M', hms.constData(), dmy.constData());
   mag_writemsg(obuf.data());
 }
 
diff --git a/nmea.cc b/nmea.cc
index 65cc8ca18950ed5cd1ec981cc97c4c0207019eb5..3366bdcc466aec2df68484e2d97ab85781fda1d1 100644 (file)
--- a/nmea.cc
+++ b/nmea.cc
@@ -1199,8 +1199,6 @@ NmeaFormat::nmea_trackpt_pr(const Waypoint* wpt)
   char obuf[200];
   char fix='0';
   int cksum;
-  time_t hms;
-  time_t ymd;
 
   if (opt_sleep) {
     gbfflush(file_out);
@@ -1220,14 +1218,11 @@ NmeaFormat::nmea_trackpt_pr(const Waypoint* wpt)
   double lat = degrees2ddmm(wpt->latitude);
   double lon = degrees2ddmm(wpt->longitude);
 
-  time_t ct = wpt->GetCreationTime().toTime_t();
-  struct tm* tm = gmtime(&ct);
-  if (tm) {
-    hms = tm->tm_hour * 10000 + tm->tm_min * 100 + tm->tm_sec;
-    ymd = tm->tm_mday * 10000 + tm->tm_mon * 100 + tm->tm_year;
-  } else {
-    hms = 0;
-    ymd = 0;
+  QByteArray dmy("");
+  QByteArray hms("");
+  if (wpt->GetCreationTime().isValid()) {
+    dmy = wpt->GetCreationTime().toUTC().toString("ddMMyy").toUtf8();
+    hms = wpt->GetCreationTime().toUTC().toString("hhmmss.zzz").toUtf8();
   }
 
   switch (wpt->fix) {
@@ -1246,14 +1241,14 @@ NmeaFormat::nmea_trackpt_pr(const Waypoint* wpt)
   }
 
   if (opt_gprmc) {
-    snprintf(obuf, sizeof(obuf), "GPRMC,%010.3f,%c,%08.3f,%c,%09.3f,%c,%.2f,%.2f,%06d,,",
-             (double) hms + (wpt->GetCreationTime().time().msec() / 1000.0),
+    snprintf(obuf, sizeof(obuf), "GPRMC,%s,%c,%08.3f,%c,%09.3f,%c,%.2f,%.2f,%s,,",
+             hms.constData(),
              fix=='0' ? 'V' : 'A',
              fabs(lat), lat < 0 ? 'S' : 'N',
              fabs(lon), lon < 0 ? 'W' : 'E',
              WAYPT_HAS(wpt, speed) ? MPS_TO_KNOTS(wpt->speed):(0),
              WAYPT_HAS(wpt, course) ? (wpt->course):(0),
-             (int) ymd);
+             dmy.constData());
     cksum = nmea_cksum(obuf);
 
     /* GISTeq doesn't care about the checksum, but wants this prefixed, so
@@ -1265,8 +1260,8 @@ NmeaFormat::nmea_trackpt_pr(const Waypoint* wpt)
     gbfprintf(file_out, "$%s*%02X\n", obuf, cksum);
   }
   if (opt_gpgga) {
-    snprintf(obuf, sizeof(obuf), "GPGGA,%010.3f,%08.3f,%c,%09.3f,%c,%c,%02d,%.1f,%.3f,M,%.1f,M,,",
-             (double) hms + (wpt->GetCreationTime().time().msec() / 1000.0),
+    snprintf(obuf, sizeof(obuf), "GPGGA,%s,%08.3f,%c,%09.3f,%c,%c,%02d,%.1f,%.3f,M,%.1f,M,,",
+             hms.constData(),
              fabs(lat), lat < 0 ? 'S' : 'N',
              fabs(lon), lon < 0 ? 'W' : 'E',
              fix,
diff --git a/reference/track/magellandate.log b/reference/track/magellandate.log
new file mode 100644 (file)
index 0000000..4851650
--- /dev/null
@@ -0,0 +1,7 @@
+$PMGNTRK,4231.829,N,08807.303,W,00210,M,032908.38,A,,070898*64\r
+$PMGNTRK,4231.829,N,08807.303,W,00210,M,032909.38,A,,070899*64\r
+$PMGNTRK,4231.829,N,08807.304,W,00210,M,032910.38,A,,070800*6B\r
+$PMGNTRK,4231.829,N,08807.304,W,00210,M,032911.38,A,,070801*6B\r
+$PMGNTRK,4231.829,N,08807.304,W,00210,M,032912.38,A,,070802*6B\r
+$PMGNTRK,4231.829,N,08807.304,W,00210,M,000000.00,A,,010103*65\r
+$PMGNCMD,END*3D\r
diff --git a/reference/track/nmeadate.gpssim b/reference/track/nmeadate.gpssim
new file mode 100644 (file)
index 0000000..586a499
--- /dev/null
@@ -0,0 +1,12 @@
+$FRSPD,0.16*66\r
+$FRWPT,4231.82910,N,08807.30330,W,209.8,070898,032908*63\r
+$FRSPD,0.16*66\r
+$FRWPT,4231.82910,N,08807.30340,W,209.7,070899,032909*6B\r
+$FRSPD,0.16*66\r
+$FRWPT,4231.82920,N,08807.30360,W,209.7,070800,032910*62\r
+$FRSPD,0.22*61\r
+$FRWPT,4231.82920,N,08807.30360,W,209.6,070801,032911*63\r
+$FRSPD,0.16*66\r
+$FRWPT,4231.82920,N,08807.30370,W,209.6,070802,032912*62\r
+$FRSPD,0.16*66\r
+$FRWPT,4231.82930,N,08807.30380,W,209.6,311202,235959*68\r
diff --git a/reference/track/nmeadate.gpx b/reference/track/nmeadate.gpx
new file mode 100644 (file)
index 0000000..d11ded6
--- /dev/null
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gpx version="1.0" creator="GPSBabel - https://www.gpsbabel.org" xmlns="http://www.topografix.com/GPX/1/0">
+  <time>1970-01-01T00:00:00Z</time>
+  <bounds minlat="42.530485000" minlon="-88.121766667" maxlat="42.530528333" maxlon="-88.121706667"/>
+  <trk>
+    <trkseg>
+      <trkpt lat="42.530485000" lon="-88.121721667">
+        <ele>209.800</ele>
+        <time>1998-08-07T03:29:08.379Z</time>
+        <course>138.919998</course>
+        <speed>0.083333</speed>
+        <geoidheight>-34.2</geoidheight>
+        <fix>2d</fix>
+        <sat>5</sat>
+        <hdop>1.600000</hdop>
+        <vdop>4.500000</vdop>
+        <pdop>4.900000</pdop>
+      </trkpt>
+      <trkpt lat="42.530485000" lon="-88.121723333">
+        <ele>209.700</ele>
+        <time>1999-08-07T03:29:09.379Z</time>
+        <course>145.850006</course>
+        <speed>0.083333</speed>
+        <geoidheight>-34.2</geoidheight>
+        <fix>3d</fix>
+        <sat>6</sat>
+        <hdop>1.600000</hdop>
+        <vdop>4.500000</vdop>
+        <pdop>4.900000</pdop>
+      </trkpt>
+      <trkpt lat="42.530486667" lon="-88.121726667">
+        <ele>209.700</ele>
+        <time>2000-08-07T03:29:10.379Z</time>
+        <course>143.250000</course>
+        <speed>0.083333</speed>
+        <geoidheight>-34.2</geoidheight>
+        <fix>dgps</fix>
+        <sat>7</sat>
+        <hdop>1.600000</hdop>
+        <vdop>4.500000</vdop>
+        <pdop>4.900000</pdop>
+      </trkpt>
+      <trkpt lat="42.530486667" lon="-88.121726667">
+        <ele>209.600</ele>
+        <time>2001-08-07T03:29:11.379Z</time>
+        <course>145.759995</course>
+        <speed>0.111111</speed>
+        <geoidheight>-34.2</geoidheight>
+        <fix>pps</fix>
+        <sat>8</sat>
+        <hdop>1.600000</hdop>
+        <vdop>4.600000</vdop>
+        <pdop>4.900000</pdop>
+      </trkpt>
+      <trkpt lat="42.530486667" lon="-88.121728333">
+        <ele>209.600</ele>
+        <time>2002-08-07T03:29:12.379Z</time>
+        <course>141.440002</course>
+        <speed>0.083333</speed>
+        <geoidheight>-34.2</geoidheight>
+        <fix>2d</fix>
+        <sat>9</sat>
+        <hdop>1.600000</hdop>
+        <vdop>4.600000</vdop>
+        <pdop>4.900000</pdop>
+      </trkpt>
+      <trkpt lat="42.530488333" lon="-88.121730000">
+        <ele>209.600</ele>
+        <time>2002-12-31T23:59:59.999Z</time>
+        <course>140.399994</course>
+        <speed>0.083333</speed>
+        <geoidheight>-34.2</geoidheight>
+        <fix>3d</fix>
+        <sat>5</sat>
+        <hdop>1.600000</hdop>
+        <vdop>4.600000</vdop>
+        <pdop>4.900000</pdop>
+      </trkpt>
+    </trkseg>
+  </trk>
+</gpx>
diff --git a/reference/track/nmeadate.nmea b/reference/track/nmeadate.nmea
new file mode 100644 (file)
index 0000000..951eca6
--- /dev/null
@@ -0,0 +1,24 @@
+$GPRMC,032908.379,A,4231.829,N,08807.303,W,0.16,138.92,070898,,*14
+$GPGGA,032908.379,4231.829,N,08807.303,W,1,05,1.6,209.800,M,-34.2,M,,*6A
+$GPVTG,138.920,T,0,M,0.162,N,0.300,K*57
+$GPGSA,A,2,,,,,,,,,,,,,4.9,1.6,4.5*38
+$GPRMC,032909.379,A,4231.829,N,08807.303,W,0.16,145.85,070899,,*18
+$GPGGA,032909.379,4231.829,N,08807.303,W,1,06,1.6,209.700,M,-34.2,M,,*67
+$GPVTG,145.850,T,0,M,0.162,N,0.300,K*5B
+$GPGSA,A,3,,,,,,,,,,,,,4.9,1.6,4.5*39
+$GPRMC,032910.379,A,4231.829,N,08807.304,W,0.16,143.25,070800,,*1B
+$GPGGA,032910.379,4231.829,N,08807.304,W,2,07,1.6,209.700,M,-34.2,M,,*6A
+$GPVTG,143.250,T,0,M,0.162,N,0.300,K*57
+$GPGSA,A,3,,,,,,,,,,,,,4.9,1.6,4.5*39
+$GPRMC,032911.379,A,4231.829,N,08807.304,W,0.22,145.76,070801,,*1C
+$GPGGA,032911.379,4231.829,N,08807.304,W,3,08,1.6,209.600,M,-34.2,M,,*64
+$GPVTG,145.760,T,0,M,0.216,N,0.400,K*50
+$GPGSA,A,*03
+$GPRMC,032912.379,A,4231.829,N,08807.304,W,0.16,141.44,070802,,*1E
+$GPGGA,032912.379,4231.829,N,08807.304,W,1,09,1.6,209.600,M,-34.2,M,,*64
+$GPVTG,141.440,T,0,M,0.162,N,0.300,K*52
+$GPGSA,A,2,,,,,,,,,,,,,4.9,1.6,4.6*3B
+$GPRMC,235959.999,A,4231.829,N,08807.304,W,0.16,140.40,311202,,*1B
+$GPGGA,235959.999,4231.829,N,08807.304,W,1,05,1.6,209.600,M,-34.2,M,,*66
+$GPVTG,140.400,T,0,M,0.162,N,0.300,K*57
+$GPGSA,A,3,,,,,,,,,,,,,4.9,1.6,4.6*3A
index b4e64141c1d58276fd76a966699b8bc27b320949..175c774e8eb539ed7f409b1977701e7ed91faf7f 100644 (file)
@@ -5,3 +5,6 @@ gpsbabel -i geo -f ${REFERENCE}/geocaching.loc -o gpssim -F ${TMPDIR}/waypoints.
 compare ${TMPDIR}/waypoints.gpssim ${REFERENCE}
 gpsbabel -i gpx -f ${REFERENCE}/track/tracks.gpx -o gpssim -F ${TMPDIR}/tracks.gpssim
 compare ${TMPDIR}/tracks.gpssim ${REFERENCE}/track
+gpsbabel -i gpx -f ${REFERENCE}/track/nmeadate.gpx -o gpssim -F ${TMPDIR}/nmeadate.gpssim
+compare ${REFERENCE}/track/nmeadate.gpssim ${TMPDIR}/nmeadate.gpssim
+
index b76fa4e321107ab413701a051be83640b5667dae..f6f4e80c146d33c6ef8fd08bf31db01959a13ad9 100644 (file)
@@ -18,3 +18,5 @@ gpsbabel -r -i magellanx -f ${REFERENCE}/route/magexplorist.rte -o magellanx -F
 gpsbabel -r -i magellanx -f ${TMPDIR}/magxfile.rte -o magellanx -F ${TMPDIR}/magxfile2.rte
 compare ${REFERENCE}/route/magexplorist.rte ${TMPDIR}/magxfile2.rte
 
+gpsbabel -t -i gpx -f ${REFERENCE}/track/nmeadate.gpx -o magellanx -F ${TMPDIR}/magellandate.log
+compare ${REFERENCE}/track/magellandate.log ${TMPDIR}/magellandate.log
index 169682979eb0ee2143a0e308ae53067da7fcd86a..3ef9e647f262eff9dd62488755d7867e7af120ba 100644 (file)
@@ -28,3 +28,6 @@ gpsbabel -t -i nmea -f ${REFERENCE}/track/backfilldate.nmea -o unicsv,utc=0 -F $
 compare ${REFERENCE}/track/backfilldate.csv ${TMPDIR}/backfilldate.csv
 gpsbabel -t -i nmea -f ${REFERENCE}/track/backfilldate2.nmea -o unicsv,utc=0 -F ${TMPDIR}/backfilldate2.csv
 compare ${REFERENCE}/track/backfilldate2.csv ${TMPDIR}/backfilldate2.csv
+
+gpsbabel -i gpx -f ${REFERENCE}/track/nmeadate.gpx -o nmea -F ${TMPDIR}/nmeadate.nmea
+compare ${REFERENCE}/track/nmeadate.nmea ${TMPDIR}/nmeadate.nmea